import { ActionTree } from 'vuex';
import type { RouteRecordRaw } from 'vue-router';
import { Role, UserState } from './typing';
import { RootState } from '@/store/root-state';
import { RESET_CURRENT_USER, SET_INFO, SET_ROUTERS, SET_TOKEN } from './mutations';
import ls from '@/utils/local-storage';
import { depthEach } from '@/utils/tree';

import {
  LoginParams,
  accountLogin,
  getCurrentUser,
  getUserInfo,
  postLogout,
  UserInfo,
} from '@/api/user/login';
import { default as router, routes } from '@/router';
import { filterMenu } from '@/utils/menu-util';
import { hasAuthority, filterChildRoute } from '@/utils/authority';
import { generatorDynamicRouter } from '@/router/generator-routers';
import { MenuDataItem } from '@/router/typing';
import { userMenu } from '@/api/user/login';

export const LOGIN = 'LOGIN';
export const LOGOUT = 'LOGOUT';
export const GET_INFO = 'GET_INFO';
export const GENERATE_ROUTES = 'GenerateRoutes';
export const GENERATE_ROUTES_DYNAMIC = '';
export const GENERATE_MENU = 'GENERATE_MENU';
// 菜单路径是否有效
const isAvailablePath = (menus, path) => {
  let has = false;
  depthEach(menus, o => {
    if (o.path === path) has = true;
  });
  return has;
};

export const actions: ActionTree<UserState, RootState> = {
  [LOGIN]({ commit }, info: LoginParams) {
    return new Promise((resolve, reject) => {
      // call ajax
      accountLogin(info)
        .then(res => {
          commit(SET_TOKEN, res.data.st);
          commit(`user/${SET_INFO}`, {
            userid: res.data.value.userId,
            name: res.data.value.userName,
            systemModel: res.data.value.systemModel || 'ZC',
          });
          resolve(res);
        })
        .catch(error => {
          reject(error);
        });
    });
  },
  [GET_INFO]({ commit }) {
    return new Promise((resolve, reject) => {
      getUserInfo()
        .then(res => {
          commit(SET_INFO, {
            userid: res.data.userId,
            name: res.data.userName,
            systemModel: res.data.systemModel || 'ZC',
            authXqdwName: res.data.authXqdwName,
          });
          resolve(res);
        })
        .catch(err => {
          // 获取登录用户信息后，直接清理掉当前 token 并强制让流程走到登录页
          commit(SET_TOKEN, null);
          reject(err);
        });
    });
  },
  // 从路由表构建路由（前端对比后端权限字段过滤静态路由表）
  [GENERATE_ROUTES]({ commit }, info: UserInfo) {
    return new Promise<RouteRecordRaw[]>(resolve => {
      // 修改这里可以根据接口返回的对象结构进行改变
      // 亦或是去掉 info.role 使用别的属性替代
      // 任何方案都可以，只需要将最后拼接构建好的路由数组使用
      // router.addRoute() 添加到当前运行时的路由中即可
      const allRoutes = filterMenu(routes);
      const allowRoutes = allRoutes;

      const menus = ls.get('user_menu');
      const menusMap = {};
      depthEach(menus, item => {
        // 菜单的redirect值
        // 如果有默认值且默认值有效则采用默认值，否则使用
        // 如果当前菜单有子菜单，则当前菜单的redirect值为
        if (item.children && item.children.length) {
          const childrenPath = item.children[0].path;
          if (item.redirect) {
            const availablePath: boolean = isAvailablePath(item.children, item.redirect);
            item.redirect = availablePath ? item.redirect : childrenPath;
          } else {
            item.redirect = childrenPath;
          }
        }
        menusMap[item.path] = item;
      });
      depthEach(allowRoutes, item => {
        if (menusMap[item.path]) {
          item.flag = true;
          if (item.children) {
            item.redirect = menusMap[item.path].redirect;
          }
        }
      });

      // 添加到路由表
      const {
        // eslint-disable-next-line
        children: _,
        ...mainRoute
      } = routes[0];
      const route = {
        ...mainRoute,
        children: allowRoutes,
      };
      router.addRoute(route);
      commit(SET_ROUTERS, allowRoutes);
      resolve(allowRoutes);
    });
  },
  // 从后端获取路由表结构体，并构建前端路由
  [GENERATE_ROUTES_DYNAMIC]({ commit }) {
    return new Promise<RouteRecordRaw>(resolve => {
      generatorDynamicRouter()
        .then((routes: RouteRecordRaw) => {
          const allowRoutes = routes.children || [];
          // 添加到路由表
          router.addRoute(routes);
          commit(SET_ROUTERS, allowRoutes);
          resolve(routes);
        })
        .catch(err => {
          console.error('generatorDynamicRouter', err);
        });
    });
  },
  // 获取菜单数据，并且转换成组件所需的数据
  [GENERATE_MENU]({ commit }) {
    return new Promise(resolve => {
      userMenu()
        .then(res => {
          console.log('res', res.data);
        })
        .catch(err => {
          console.log('err=', err);
        });
    });
  },
  [LOGOUT]({ commit }, info) {
    return new Promise<void>(resolve => {
      postLogout(info).finally(() => {
        commit(SET_TOKEN, null);
        commit(RESET_CURRENT_USER);
        router.push('/user/login');
        resolve();
      });
    });
  },
};
